import { provide, ref, h, computed, watch } from 'vue';
import { ElNotification, ElLoading, ElMessage } from 'element-plus';
import { ResultEnum } from "@/enums/httpEnum";
import queueComponent from './index.vue';
import Item from '../MerakCollapse/Item.vue';



type T = any;
interface queueConfig {
    postFn: Function, //批处理上传接口
    otherParams: Object,//额外参数
    queueDataList: Array<T>,//批处理数据
    key?: string, //提取队列数据中指定的key，生成新的 数组
    step: number, //单次上传数量
    duration?: number // 自动关闭,默认不关闭
    callback: Function//回调
}

const help = [
    `================== 前端批量处理组件使用方法 ==================`,
    ` 组件使用： <batchQueueComponent></batchQueueComponent>`,
    `proxy : 'const { proxy } = getCurrentInstance();'`,
    `import UseQueueModule from '@/components/MerakBatchProcessQueue/index.ts';`,
    `msgConfig 是翻译文案配置 以下是固定格式（不传为默认值）：{`, 
    ` success: 操作成功`,
    ` successTipsSub: 全部操作完成`,
    ` batchDialogTitleResult: "操作结果",`,
    ` batchDialogTitleIng: "操作中",`,
    ` batchStop: "终止操作",`,
    ` batchCancel: "确认"`,
    ` };`,
    `const {batchQueueComponent,batchQueue, batchQueueRun} =UseQueueModule(proxy,msgConfig);`,
    `   batchQueueRun({//在需要的地方 起动 批量处理程序 `,
    `     mode:"simple",//simple简单版本，没有弹窗，只有loading和结果提示，默认值:无`,
    `     loadingContext:".el-main",//显示loading 的上下文（className） 默认.el-main ，mode:"simple"时生效`,
    `     postFn:getGoodsTypeTableHeadApi,//批处理接口 axios 必须返回 promise，返回值 {code:2000,data:{errorList:['错误1'，'错误2']}}，没有错误 errorList:[]`,
    `     params: {3: "3", 4: "4"},//额外参数`,
    `     queueDataList: list,//队列参数 type:数组，`,
    `     queueApiKey: "pro_id",//post 数据 批量队列参数，用来替换 queue 字段名，`,
    `     key:'id' ,//如果你的 queueDataList 是个数据对象，可以通过指定提取 key 的方式，来获取到队列数据`,
    `     step:2 // 单次上传数量`,
    `     duration: number // 自动关闭(只在没有错误的时候生效),默认不关闭`,
    `   });`,


    ` axios 返回数据格式： `,
    ` {
        "code": 4200,
        "message": "fail",
        "errors": [
            {
                "key": "QF001_NEW11_952_1751_79",
                "message": "请填写[生产国家], 请填写商品目录"
            },
            {
                "key": "QF001_0033",
                "message": "请填写商品目录请填写商品目录"
            }
        ],
        "data": []
    }`



]
const errorList = ref<[]>([])

const defaultMsg = {
    batchDialogTitle: "",
    success: `merak.action_success`,
    successTipsSub: `merak.all_action_success`,
    batchDialogTitleResult: "merak.action_result",
    batchDialogTitleIng: "merak.action_ing",
    batchStop: "merak.action_stop",
    batchCancel: "merak.confirm"
}
let msg = {};
const printHelp = () => {
    help.map((item, index) => {
        console.log(item)
    })
}
const btachQueueModule = (proxy, msgConfig={}): object => {
    const batchQueue = ref<[]>();
    const batchQueueLength = ref(0);
    const progressDialogVisible = ref<boolean>(false);
    const batchPercentage = ref<number>(0);
    const step = ref<number>(1000);
    const sent = ref<[]>([]);
    const batchResultVisible = ref<boolean>(false);
    const durationTime = ref<number>(0);
    let loadingInstance = null;
    let curConfig = {};




    /**
      * 批量队列执行函数
      * @param config 配置对象，包含队列数据列表和后续操作函数等配置
      * - config.queueDataList: 队列数据列表，不能为空
      * - config.postFn: 执行完毕后的回调函数，不能为空
      * - config.step: 可选，步进值，用于控制处理的步进
      * - config.key: 可选，用于格式化数据时的键值
      * 该函数不返回任何内容
      */
    const batchQueueRun = (config: queueConfig): Promise<any> => {
        //重置数据状态
        errorList.value = [];
        batchResultVisible.value = false;
        sent.value = [];
        batchPercentage.value = 0;
        msg.batchDialogTitle = msg.batchDialogTitleIng;
        curConfig = config;
        // 检查队列数据列表是否存在
        if (!config.queueDataList) {
            ElNotification({
                title: 'batchQueueRun 方法',
                message: h('span', { style: 'color: red' }, 'queueDataList 必须存在'),
            })
            return
        }

        // 检查postFn是否存在
        if (!config.postFn) {
            ElNotification({
                title: 'batchQueueRun 方法',
                message: h('span', { style: 'color: red' }, 'postFn 必须存在 , 需要 api 中封装的接口'),
            })
            return
        }

        // 如果存在step配置，则更新step值
        if (config.step) {
            step.value = config.step;
        }

        // 格式化数据并更新batchQueue的值
        batchQueue.value = formatData(config.queueDataList, config.key || null)

        if (config?.mode == 'simple') { //简单模式
            loadingShow();
        } else {
            progressDialogVisible.value = true; // 显示进度对话框
        }
        post(config); // 执行post操作
    }


    /**
     * 根据提供的键(key)从队列数据列表中提取数据或返回整个列表。
     * @param queueDataList - 待处理的数据列表，列表中每个项应为一个对象。
     * @param key - 如果提供此参数，则函数将返回一个由列表中每个对象的该键对应的值组成的新列表；否则，直接返回原列表。
     * @returns 返回根据key提取后的值组成的列表，或整个原始列表。
     */
    const formatData = (queueDataList, key) => {
        // 复制输入列表以避免直接修改原数据
        const list = JSON.parse(JSON.stringify(queueDataList));
        let result: [] = [];
        if (key) {
            // 如果提供了key，遍历列表并提取每个项的key对应的值
            list.map((item) => {
                result.push(item[key])
            })
        } else {
            // 如果没有提供key，直接返回整个列表
            result = list
        }
        batchQueueLength.value = list.length
        return result
    }

    const loadingShow = (): Promise<any> => {
        loadingInstance = ElLoading.service({
            target: ".el-main"
        })
        return Promise.resolve();
    }
    const loadingHide = (): Promise<any> => {
        loadingInstance.close()
        return Promise.resolve();
    }

    /**
    * 执行批量发送操作的函数。
    * @param config 包含发送配置的对象，必须包含 postFn 方法用于实际发送数据，以及可选的 params 参数对象。
    */
    const post = (config) => {
        // 如果发送队列为空，则延迟1.5秒后显示结果弹窗
        if (batchQueue.value?.length == 0) {
            setTimeout(() => {
                if (config?.mode == 'simple') { //简单模式
                    loadingHide();
                   
                    if (errorList.value.length == 0) {
                        ElMessage({
                            type: 'success',
                            message: msg.success,
                            duration: config?.duration * 1000 || 0
                        })
                    } else {
                        function createdText(errorList) {
                            let str = ``; 
                          
                            errorList.map((item) => {
                                
                                str += `<div style="line-height:18px"><b>${item.key}</b>: ${item.message}</div>${errorList.length>1?'</br>':''}`
                            })
                            return str;
                        }
                        ElMessage({
                            type: 'error',
                            showClose: true,
                            duration: 0,
                            dangerouslyUseHTMLString: true,
                            customClass:"batch_error_list",
                            message: createdText(errorList.value)
                        })
                    }

                } else {
                    batchResultVisible.value = true;
                    msg.batchDialogTitle = msg.batchDialogTitleResult;
                    console.log(errorList)
                    if (config?.duration && batchResultVisible.value && errorList.value.length == 0) {
                        durationClose(config);
                    }
                }
                config.callback();
            }, 1500);
           
            return
        }

        // 从发送队列中取出当前要处理的数据分组
        let curQueue = batchQueue.value?.splice(0, step.value);
        // 将当前处理的数据分组加到已发送列表中
        sent.value = sent.value.concat(curQueue)

        // 调用配置中提供的发送函数，传入当前处理的数据分组
        let postData = {
            ...config.params || {},
            [config.queueApiKey || 'queue']: curQueue
        };

        config.postFn(postData).then(res => {
            console.log(res)
            if (res.code == ResultEnum.SUCCESS) {

                // 递归调用自身，处理下一个数据分组
                post(config);
            }
            if (res.code == ResultEnum.BUSINESSERROR) {
                errorList.value = errorList.value.concat(res.errors);
                console.log(errorList.value)
                // 递归调用自身，处理下一个数据分组
                post(config);
            }
            // 更新发送进度
            if (res.code == ResultEnum.ERROR) {
                batchQueue.value = []

            }
            batchPercentage.value = (sent.value.length / batchQueueLength.value * 100).toFixed(2)
        }).catch(e => {
            // 如果发送过程中出现错误，打印错误并尝试重新发送
            console.log(e)
            post(config);
        })
    }

    /**
        * 停止当前操作，清空批处理队列并隐藏进度对话框。
        * 
        * 该函数不接受任何参数。
        * 
        * 该函数没有返回值。
        */
    const stop = () => {
        // 清空批处理队列
        batchQueue.value = [];
        // 隐藏进度对话框
        progressDialogVisible.value = false;
    }



    const durationClose = (config) => {
        let step = config.duration;
        durationTime.value = step;
        window.timer = setInterval(() => {
            step--;
            if (step <= 0) {
                progressDialogVisible.value = false;
                clearInterval(window.timer)
            }
            durationTime.value = step;
        }, 1000)

    }
    const batchHandleClose = () => {
        progressDialogVisible.value = false;
        clearInterval(window.timer);
        // curConfig.callback()
    }
    const lang = () => {
        Object.keys(defaultMsg).map(key => {
            defaultMsg[key] = proxy.$t(defaultMsg[key])
        })
    }
    lang();
    msg = Object.assign({}, defaultMsg, msgConfig);



    /**
       * 注册全局变量或服务到Vue的上下文中，使得在组件内可以方便地使用这些变量或服务。
       * @param key 注册的变量或服务的名称。
       * @param value 注册的变量或服务的值。
       */
    provide('batchQueue', batchQueue);
    provide('progressDialogVisible', progressDialogVisible);
    provide('batchPercentage', batchPercentage);
    provide('batchResultVisible', batchResultVisible);
    provide('batchDurationTime', durationTime);
    provide('batchHandleClose', batchHandleClose);
    provide('batchErrorList', errorList);
    provide('batchMsg', msg);
    provide('batchStop', stop);

    // 总结注释：这里提供的是一系列与批量处理相关的状态或数据，包括队列、进度对话框可见性、
    // 批量处理百分比、结果对话框可见性、错误列表、消息以及停止操作的控制，这些被提供的状态或数据
    // 可以在组件中直接访问和使用，从而实现状态的共享和管理。



    return {
        batchQueueComponent: queueComponent,
        batchQueue,
        batchQueueRun,
        batchHelp: printHelp
    }
}

export default btachQueueModule;



